#pragma once

#include <functional>
#include <sys/poll.h>
#include <unistd.h>
#include "poll_poller.h"
#include "trace.h"
class channel : public std::enable_shared_from_this<channel>
{
  public:
    channel(poll_poller* poller) : poller_(poller)
    {
    }
    ~channel()
    {
        if (fd_ > 0)
            close(fd_);
    }

    int fd() const
    {
        return fd_;
    }

    void set_read_callback(std::function<void()> func)
    {
        read_callback_ = func;
    }
    void set_write_callback(std::function<void()> func)
    {
        write_callback_ = func;
    }
    void set_close_callback(std::function<void()> func)
    {
        close_callback_ = func;
    }
    void set_error_callback(std::function<void()> func)
    {
        error_callback_ = func;
    }

    void handle_read()
    {
        if (read_callback_) {
            read_callback_();
        }
        else {
            TRACE_DEBUG("no read callback");
        }
    }
    void handle_write()
    {
        if (write_callback_) {
            write_callback_();
        }
        else {
            TRACE_DEBUG("no write callback");
        }
    }
    void handle_close()
    {
        if (close_callback_) {
            close_callback_();
        }
        else {
            TRACE_DEBUG("no close callback");
        }
    }
    void handle_error()
    {
        if (error_callback_) {
            error_callback_();
        }
        else {
            TRACE_DEBUG("no error callback");
        }
    }

    int events() const
    {
        return events_;
    }

    void set_read_event()
    {
        events_ |= (POLLIN | POLLPRI);
        update();
    }

    void set_write_event()
    {
        events_ |= POLLOUT;
        update();
    }

    void set_no_read_event()
    {
        events_ &= ~(POLLIN | POLLPRI);
        update();
    }

    void set_no_write_event()
    {
        events_ &= ~POLLOUT;
        update();
    }
    void set_no_event()
    {
        events_ = 0;
        update();
    }

    bool is_no_event() const
    {
        return events_ == 0;
    }

    void set_index(int index)
    {
        index_ = index;
    }

    int index() const
    {
        return index_;
    }

  private:
    void update()
    {
        poller_->update_channel(shared_from_this());
    }

  protected:
    poll_poller* poller_;
    int          fd_;
    int          events_ = 0;
    int          index_;
    using call_back_funs_t = std::function<void()>;
    call_back_funs_t read_callback_;
    call_back_funs_t write_callback_;
    call_back_funs_t close_callback_;
    call_back_funs_t error_callback_;
};